#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Copyright (c) 2025 粤港澳大湾区（广东）国创中心

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program.  If not, see <https://www.gnu.org/licenses/>.

File: CAEMainWindow.py
Desc: Main window class for the PyCAEPre application.
Author: xumanjia
Date: 2025-08-01
"""

from Pub.configLoad import global_scope
import re
import os
from PyQt5.QtCore import Qt,QEvent,QThread, pyqtSignal
from PyQt5.QtGui import QIcon, QFont, QKeySequence,QTextCursor
from PyQt5.QtWidgets import  QPushButton, QVBoxLayout, QWidget, QDockWidget, \
      QComboBox, QHBoxLayout, QStatusBar,QCheckBox,QLineEdit,QFileDialog, QInputDialog,QAction,\
            QDesktopWidget, QSplitter,QMenu,QButtonGroup,QRadioButton
from PySARibbon import SARibbonMainWindow, SARibbonBar, SARibbonCategory
from Dialog.PythonCodeEditor import PythonEditor # type: ignore
from Dialog.DialogData import InputDialog # type: ignore
from Dialog.PythonMeshDlg import MeshDialog # type: ignore
from Dialog.PythonFeatureTreeDlg import InputFeatureTreeDlg
from Pub.CAD import cadView 
from Pub.image import *
from Function.onCataegoryFile import *
from Function.onCataegoryModel import *
from Dialog.PythonConsoleDlg import *
from Function.onCataegoryGeometry import *
from Function.onCataegorySimulation import *
from Dialog.PythonObjectTree import *

from Dialog.PythonRightDlg import *

class MainWindow(SARibbonMainWindow):
    def __init__(self, parent=None):
        super().__init__(parent)
        if False == self.init_CAD_Env():
            return
        self.initWidgets()

    def initWidgets(self):       
        # 设置标题
        current_dir = os.path.dirname(os.path.abspath(__file__))
        self.setWindowIcon(QIcon(current_dir + '/../resource/ncti.ico'))
        self.setWindowTitle("Python CAD/CAE前处理")
        self.setGeometry(100, 100, 1600, 900)
        self.fontSize = self.getFontSize()
        self.objectTreeDocWidget = QDockWidget(self)
        self.objectTree = PythonObjectTree(self.objectTreeDocWidget)
        self.objectTreeTitleBar = PythonObjectTreeTitleBar(self.objectTreeDocWidget)
        self.objectTreePanVisable = True
        self.updateTree()
        self.rightDocWidget = QDockWidget(self)
        self.rightView = PythonRightView(self.rightDocWidget)
        self.rightDocTitleBar = PythonObjectTreeTitleBar(self.rightDocWidget)
        self.rightPanVisable = True
 
        self.setStatusBar(QStatusBar())
        #RibbonBar
        ribbon = self.ribbonBar()

        categoryFile = ribbon.addCategoryPage('文件')
        self.createCategoryFile(categoryFile)
        categoryMain = ribbon.addCategoryPage('常规')
        self.createCategoryModel(categoryMain)
        categoryGeo = ribbon.addCategoryPage('几何')
        self.createCategoryGeometry(categoryGeo)
        categorySim = ribbon.addCategoryPage('仿真')
        self.createCategorySimulation(categorySim)
        ribbon.setRibbonStyle(SARibbonBar.OfficeStyleTwoRow)
        self.NCTI.SetPyInputDialogCallback(InputDialog)
        self.NCTI.SetPyCustomDialogCallbackFun(InputFeatureTreeDlg)
        self.NCTI.SetPyMeshSettingCallbackFun(MeshDialog)
        self.InitWindowLayout()
        self.initObjectTreeDocWidget()
        self.initRightDocWidget()

        self.show()
    
    def InitWindowLayout(self):
        current_dir = os.path.dirname(os.path.abspath(__file__))
        #右边上方按钮
        button_size = (150, 30)
        self.run_script_button = QPushButton("执行", self)
        self.run_script_button.setIcon(QIcon(current_dir + '/../resource/General/script_run.svg')) 
        self.run_script_button.setFixedSize(*button_size)
        self.run_script_button.clicked.connect(self.on_run_script_button_click)
        self.open_script_button = QPushButton("打开脚本", self)
        self.open_script_button.setIcon(QIcon(current_dir + '/../resource/General/open.svg')) 
        self.open_script_button.setFixedSize(*button_size)
        self.open_script_button.clicked.connect(self.on_open_script_button_click)
        self.button_layout = QHBoxLayout() 
        self.button_layout.addWidget(self.open_script_button)
        self.button_layout.addWidget(self.run_script_button)
        self.button_widget = QWidget()
        self.button_widget.setLayout(self.button_layout)

        #右边窗口布局
        self.right_layout = QVBoxLayout()
        self.editor_script = PythonEditor()
        self.right_layout.addWidget(self.button_widget)
        self.right_layout.addWidget(self.editor_script)
        self.right_widget = QWidget(self)
        self.right_widget.setLayout(self.right_layout)
        self.right_widget.setStyleSheet("background-color: rgb(245,245,245);")
        # 把编辑器加入到右边docwidget
        current_dir = os.path.dirname(os.path.abspath(__file__))
        self.mIconScript = QIcon(current_dir + '/../resource/Tree/script_editor.svg')
        self.rightView.sideBar.addButtonDynamically(icon=self.mIconScript, buttonName="脚本编辑", widget=self.right_widget)
        self.mIconProperty = QIcon(current_dir + '/../resource/Tree/property.svg')
        self.rightView.sideBar.addButtonDynamically(icon=self.mIconProperty, buttonName="属性", widget=self.rightView.objectProperty)
        self.rightView.sideBar.setCurrentIndex(0)
        self.rightView.sideBar.buttons[0].setChecked(True)
        self.rightView.update()

        #拆分器：视图窗口和控制台
        self.splitter = QSplitter()
        self.cad_view = cadView("", self)
        self.cad_view.setStyleSheet(
            "QLabel { background-color: rgb(238, 242, 255); border-radius: 15px; min-height: 200px; min-width: 200px; }"
        )
        self.consoleDlg = PythonConsoleDlg(self)
        sys.stdout = QTextEditLogger(self.consoleDlg)
        sys.stderr = sys.stdout 

        self.splitter.setOrientation(Qt.Vertical)
        self.splitter.addWidget(self.cad_view)
        self.splitter.addWidget(self.consoleDlg)
        self.splitter.setStretchFactor(0, 3)
        self.splitter.setStretchFactor(1, 1)

        self.mainSplitter = QSplitter()
        self.mainSplitter.addWidget(self.objectTreeDocWidget)
        self.mainSplitter.addWidget(self.splitter)
        self.mainSplitter.addWidget(self.rightDocWidget)
        self.mainSplitter.setStretchFactor(0, 1)
        self.mainSplitter.setStretchFactor(1, 3)
        self.mainSplitter.setStretchFactor(2, 1)

        #主水平布局
        main_layout = QHBoxLayout()
        main_layout.addWidget(self.mainSplitter)

        #中心部件
        self.central_widget = QWidget(self)
        self.central_widget.setLayout(main_layout)
        self.setCentralWidget(self.central_widget)
        #视图窗口句柄
        self.hwnd = int(self.cad_view.winId())
        
        #设置显示模式
        self.visualmode_body.setChecked(False)
        self.visualmode_face.setChecked(True)
        self.visualmode_line.setChecked(True)
        self.visualmode_vertex.setChecked(False)


    def createCategoryFile(self, page: SARibbonCategory):
        pannel = page.addPannel('文档')
        pannel.setStyleSheet("font-size: {}pt".format(self.fontSize))

        current_dir = os.path.dirname(os.path.abspath(__file__))
        
        act = QAction(svg_to_ico(current_dir + '/../resource/General/new_part.svg'),'创建文档',self)
        pannel.addLargeAction(act)
        act.triggered.connect(lambda:on_new_button_click(self))
        
        act = QAction(svg_to_ico(current_dir + '/../resource/General/open.svg'),'打开文件',self)
        act.setShortcut(QKeySequence('Ctrl+O'))
        pannel.addLargeAction(act)
        act.triggered.connect(lambda:on_open_button_click(self))
        
        act = QAction(svg_to_ico(current_dir + '/../resource/General/save.svg'),'保存文件',self)
        act.setShortcut(QKeySequence('Ctrl+S'))
        pannel.addLargeAction(act)
        act.triggered.connect(lambda:on_save_button_click(self))
        
        act = QAction(svg_to_ico(current_dir + '/../resource/General/close.svg'), '关闭文档',self)
        act.setShortcut(QKeySequence('Ctrl+W'))
        pannel.addLargeAction(act)
        act.triggered.connect(lambda:on_close_button_click(self))

        pannel.addSeparator() 
        act = QAction(svg_to_ico(current_dir + '/../resource/Geometry/delete.svg'), '清空文档',self)
        pannel.addLargeAction(act)
        act.triggered.connect(lambda:on_clear_button_click(self))
        
        # pannel.addSeparator()   # 分割线

        pannelHis = page.addPannel('历史')
        pannelHis.setStyleSheet("font-size: {}pt".format(self.fontSize))

        act = QAction(self)
        act.setObjectName('Undo')
        act.setText('撤销')
        act.setToolTip('撤销')
        act.setIcon(svg_to_ico(current_dir + '/../resource/General/undo.svg'))
        act.setShortcut(QKeySequence('Ctrl+Z'))
        pannelHis.addLargeAction(act)
        act.triggered.connect(lambda:on_undo_button_click(self))

        act = QAction(self)
        act.setObjectName('Redo')
        act.setText('重做')
        act.setToolTip('重做')
        act.setIcon(svg_to_ico(current_dir + '/../resource/General/redo.svg'))
        act.setShortcut(QKeySequence('Ctrl+Y'))
        pannelHis.addLargeAction(act)
        act.triggered.connect(lambda:on_redo_button_click(self))
        
        pannelModel = page.addPannel('模型')
        pannelModel.setStyleSheet("font-size: {}pt".format(self.fontSize))
        act = QAction(svg_to_ico(current_dir + '/../resource/General/import.svg'), '导入模型',self)
        pannelModel.addLargeAction(act)
        act.triggered.connect(lambda:importFile(self))
        act = QAction(svg_to_ico(current_dir + '/../resource/General/export.svg'), '导出文件',self)
        pannelModel.addLargeAction(act)
        act.triggered.connect(lambda:on_export_button_click(self))

        pannelModel.addSeparator() 
        act = QAction(svg_to_ico(current_dir + '/../resource/General/delete.svg'), '删除模型',self)
        pannelModel.addLargeAction(act)
        act.triggered.connect(lambda:on_delete_button_click(self))


    def createCategoryModel(self, page: SARibbonCategory):
        pannelView = page.addPannel('视图')
        pannelView.setStyleSheet("font-size: {}pt".format(self.fontSize))

        current_dir = os.path.dirname(os.path.abspath(__file__))
        act = QAction(svg_to_ico(current_dir + '/../resource/General/show_all_model.svg'), '全部显示',self)
        act.triggered.connect(lambda:on_display_all(self))
        pannelView.addLargeAction(act)

        act = QAction(svg_to_ico(current_dir + '/../resource/General/hide_select_model.svg'), '选中隐藏',self)
        act.triggered.connect(lambda:on_hide_selected(self))
        pannelView.addLargeAction(act)

        act = QAction(svg_to_ico(current_dir + '/../resource/General/show_select_model.svg'), '选中独显',self)
        act.triggered.connect(lambda:on_diaplay_selected_only(self))
        pannelView.addLargeAction(act)

        pannelView.addSeparator() 

        act = QAction(svg_to_ico(current_dir + '/../resource/General/xplus.svg'), '',self)
        act.triggered.connect(lambda:on_zoom_view(self,3))
        pannelView.addSmallAction(act)

        act = QAction(svg_to_ico(current_dir + '/../resource/General/yplus.svg'), '',self)
        act.triggered.connect(lambda:on_zoom_view(self,4))
        pannelView.addSmallAction(act)

        act = QAction(svg_to_ico(current_dir + '/../resource/General/zplus.svg'), '',self)
        act.triggered.connect(lambda:on_zoom_view(self,0))
        pannelView.addSmallAction(act)

        act = QAction(svg_to_ico(current_dir + '/../resource/General/xminus.svg'), '',self)
        act.triggered.connect(lambda:on_zoom_view(self,2))
        pannelView.addSmallAction(act)

        act = QAction(svg_to_ico(current_dir + '/../resource/General/yminus.svg'), '',self)
        act.triggered.connect(lambda:on_zoom_view(self,5))
        pannelView.addSmallAction(act)

        act = QAction(svg_to_ico(current_dir + '/../resource/General/zminus.svg'), '',self)
        act.triggered.connect(lambda:on_zoom_view(self,1))
        pannelView.addSmallAction(act)

        pannelView.addSeparator() 

        act = QAction(svg_to_ico(current_dir + '/../resource/General/isometric.svg'), '西南视图',self)
        act.triggered.connect(lambda:on_zoom_view(self,6))
        pannelView.addLargeAction(act)

        act = QAction(svg_to_ico(current_dir + '/../resource/General/location.svg'), '恢复原位',self)
        act.triggered.connect(lambda:on_zoom_button_click(self))
        pannelView.addLargeAction(act)

        pannelView.addSeparator() 
        act = QAction(svg_to_ico(current_dir + '/../resource/General/display_mode.svg'), '显示模式',self)
        act.setEnabled(False)
        pannelView.addLargeAction(act)
        
        self.visualmode_body = QCheckBox("体")
        self.visualmode_body.stateChanged.connect(lambda state:on_visual_checkbox_body(self, state))
        pannelView.addSmallWidget(self.visualmode_body)
        
        self.visualmode_face = QCheckBox("面")
        self.visualmode_face.stateChanged.connect(lambda state:on_visual_checkbox_face(self, state))
        pannelView.addSmallWidget(self.visualmode_face)
        
        self.visualmode_line = QCheckBox("线")
        self.visualmode_line.stateChanged.connect(lambda state:on_visual_checkbox_line(self, state))
        pannelView.addSmallWidget(self.visualmode_line)
        
        self.visualmode_vertex = QCheckBox("点")
        self.visualmode_vertex.stateChanged.connect(lambda state:on_visual_checkbox_vertex(self, state))
        pannelView.addSmallWidget(self.visualmode_vertex)

        act = QAction(svg_to_ico(current_dir + '/../resource/General/selection_mode.svg'), '选择模式',self)
        act.setEnabled(False)
        pannelView.addLargeAction(act)
        
        self.selmode_body = QCheckBox("体")
        self.selmode_body.stateChanged.connect(lambda state:on_sel_checkbox_body(self, state))
        pannelView.addSmallWidget(self.selmode_body)
        
        self.selmode_face = QCheckBox("面")
        self.selmode_face.stateChanged.connect(lambda state:on_sel_checkbox_face(self, state))
        pannelView.addSmallWidget(self.selmode_face)
        
        self.selmode_line = QCheckBox("线")
        self.selmode_line.stateChanged.connect(lambda state:on_sel_checkbox_line(self, state))
        pannelView.addSmallWidget(self.selmode_line)
        
        self.selmode_vertex = QCheckBox("点")
        self.selmode_vertex.stateChanged.connect(lambda state:on_sel_checkbox_vertex(self, state))
        pannelView.addSmallWidget(self.selmode_vertex)
    
        act_allsel = QAction(svg_to_ico(current_dir + '/../resource/General/select_all.svg'), '全选',self)
        act_allsel.triggered.connect(lambda:on_allsel_button_click(self))
        pannelView.addLargeAction(act_allsel)
        
        pannelView.addSeparator() 

        act_airecognition = QAction(svg_to_ico(current_dir + '/../resource/General/ai_recognition.svg'), 'AI识别',self)
        act_airecognition.triggered.connect(lambda:on_airecog_button_click(self))
        pannelView.addLargeAction(act_airecognition)

        act_fillreasoning = QAction(QIcon(current_dir + '/../resource/AI/fillet_reasoning.png'), '圆角推理',self)
        act_fillreasoning.triggered.connect(lambda:on_zoom_button_click(self))
        pannelView.addLargeAction(act_fillreasoning)
        
        act_featurelist = QAction(QIcon(current_dir + '/../resource/AI/feature_list.png'), '特征列表',self)
        act_featurelist.triggered.connect(lambda:on_zoom_button_click(self))
        pannelView.addLargeAction(act_featurelist)

        pannelView.addSeparator() 
        act_searchloop = QAction(svg_to_ico(current_dir + '/../resource/General/search_innerloop.svg'), '查找内环',self)
        act_searchloop.triggered.connect(lambda:on_searchloop_button_click(self))
        pannelView.addLargeAction(act_searchloop)

        act_searchconnect = QAction(svg_to_ico(current_dir + '/../resource/General/search_connection.svg'), '查找连接',self)
        act_searchconnect.triggered.connect(lambda:on_searchface_button_click(self))
        pannelView.addLargeAction(act_searchconnect)

        act_noplane_connect = QAction(svg_to_ico(current_dir + '/../resource/General/nonplanar_connection.svg'), '非平面连接',self)
        act_noplane_connect.triggered.connect(lambda:on_searchnoplaneface_button_click(self))
        pannelView.addLargeAction(act_noplane_connect)

        measure_menu = QMenu("几何测量", self)
        #measure_menu.setStyleSheet("font-size: {}pt".format(self.fontSize))
        # 添加菜单项
        getpt_action = QAction(svg_to_ico(current_dir + '/../resource/General/point.svg'), "获取点", self)
        getpt_action.triggered.connect(lambda:on_measure_getpt_click(self))
        measure_menu.addAction(getpt_action)
        
        getlen_action = QAction(svg_to_ico(current_dir + '/../resource/General/length.svg'), "获取长度", self)
        getlen_action.triggered.connect(lambda:on_measure_getlen_click(self))
        measure_menu.addAction(getlen_action)
        
        getmidpt_action = QAction(svg_to_ico(current_dir + '/../resource/General/midpoint.svg'), "获取中点", self)
        getmidpt_action.triggered.connect(lambda:on_measure_getmidpt_click(self))
        measure_menu.addAction(getmidpt_action)

        getcirpt_action = QAction(svg_to_ico(current_dir + '/../resource/General/circlepoint.svg'), "获取圆点", self)
        getcirpt_action.triggered.connect(lambda:on_measure_getcenter_click(self))
        measure_menu.addAction(getcirpt_action)

        getradius_action = QAction(svg_to_ico(current_dir + '/../resource/General/radius.svg'), "获取半径", self)
        getradius_action.triggered.connect(lambda:on_measure_getradius_click(self))
        measure_menu.addAction(getradius_action)

        getvet_action = QAction(svg_to_ico(current_dir + '/../resource/General/vector.svg'), "获取向量", self)
        getvet_action.triggered.connect(lambda:on_getvec_button_click(self))
        measure_menu.addAction(getvet_action)

        getangle_action = QAction(svg_to_ico(current_dir + '/../resource/General/angle.svg'), "获取角度", self)
        getangle_action.triggered.connect(lambda:on_getangle_button_click(self))
        measure_menu.addAction(getangle_action)

        act_measure = QAction(svg_to_ico(current_dir + '/../resource/General/measure.svg'), '几何测量',self)
        act_measure.triggered.connect(measure_menu.show)
        
        act_measure.setMenu(measure_menu)
        pannelView.addLargeAction(act_measure)


    def createCategoryGeometry(self,page: SARibbonCategory):
        pannelView = page.addPannel('几何')
        pannelView.setStyleSheet("font-size: {}pt".format(self.fontSize))
        current_dir = os.path.dirname(os.path.abspath(__file__))
        act = QAction(svg_to_ico(current_dir + '/../resource/Geometry/box.svg'), '长方体',self)
        act.triggered.connect(lambda:on_exec_box_button_click(self))
        pannelView.addLargeAction(act)
        
        act = QAction(svg_to_ico(current_dir + '/../resource/Geometry/cylinder.svg'), '圆柱体',self)
        act.triggered.connect(lambda:on_exec_cylinder_button_click(self))
        pannelView.addLargeAction(act)
        pannelView.addSeparator() 

        act = QAction(svg_to_ico(current_dir + '/../resource/Geometry/boolean.svg'), '布尔',self)
        act.triggered.connect(lambda:on_exec_boole_button_click(self))
        pannelView.addLargeAction(act)

        act = QAction(svg_to_ico(current_dir + '/../resource/Geometry/fillet.svg'), '圆角',self)
        act.triggered.connect(lambda:on_exec_fillet_button_click(self))
        pannelView.addLargeAction(act)

        pannelView.addSeparator() 
        pannelView = page.addPannel('draft_geo')
        pannelView.setStyleSheet("font-size: {}pt".format(self.fontSize))
        act = QAction(svg_to_ico(current_dir + '/../resource/Geometry/chamfer.svg'), '斜角',self)
        act.triggered.connect(lambda:on_exec_chamfer_button_click(self))
        pannelView.addLargeAction(act)

        act = QAction(svg_to_ico(current_dir + '/../resource/Geometry/pan.svg'), '平移',self)
        act.triggered.connect(lambda:on_exec_pan_button_click(self))
        pannelView.addLargeAction(act)

        act = QAction(svg_to_ico(current_dir + '/../resource/Geometry/zoom.svg'), '缩放',self)
        act.triggered.connect(lambda:on_exec_scale_button_click(self))
        pannelView.addLargeAction(act)

        act = QAction(svg_to_ico(current_dir + '/../resource/Geometry/rotate.svg'), '旋转',self)
        act.triggered.connect(lambda:on_exec_rotate_button_click(self))
        pannelView.addLargeAction(act)
        pannelView.addSeparator() 

        act = QAction(svg_to_ico(current_dir + '/../resource/Geometry/remove_features.svg'), '移除特征',self)
        act.triggered.connect(lambda:on_exec_removefeature_button_click(self))
        pannelView.addLargeAction(act)

        act = QAction(svg_to_ico(current_dir + '/../resource/Geometry/removing_faces.svg'), '移除面',self)
        act.triggered.connect(lambda:on_exec_removeface_button_click(self))
        pannelView.addLargeAction(act)

        act = QAction(svg_to_ico(current_dir + '/../resource/Geometry/extract_cell.svg'), '抽取要素',self)
        act.triggered.connect(lambda:on_exec_extractcell_button_click(self))
        pannelView.addLargeAction(act)

        act = QAction(svg_to_ico(current_dir + '/../resource/Geometry/fill_loop.svg'), '填充内环',self)
        act.triggered.connect(lambda:on_exec_fillloop_button_click(self))
        pannelView.addLargeAction(act)

        act = QAction(svg_to_ico(current_dir + '/../resource/Geometry/create_compound.svg'), '组合',self)
        act.triggered.connect(lambda:on_exec_createcompound_button_click(self))
        pannelView.addLargeAction(act)

        act = QAction(svg_to_ico(current_dir + '/../resource/Geometry/explode_body.svg'), '分解',self)
        act.triggered.connect(lambda:on_exec_explodeboldy_button_click(self))
        pannelView.addLargeAction(act)

        act = QAction(svg_to_ico(current_dir + '/../resource/Geometry/sewing_bodies.svg'), '缝合',self)
        act.triggered.connect(lambda:on_exec_sewingbodies_button_click(self))
        pannelView.addLargeAction(act)

        act = QAction(svg_to_ico(current_dir + '/../resource/Geometry/separating_surface.svg'), '分离面',self)
        act.triggered.connect(lambda:on_exec_splitface_button_click(self))
        pannelView.addLargeAction(act)

        act = QAction(svg_to_ico(current_dir + '/../resource/Geometry/extrude.svg'), '拉伸',self)
        act.triggered.connect(lambda:on_exec_prism_button_click(self))
        pannelView.addLargeAction(act)

        act = QAction(svg_to_ico(current_dir + '/../resource/Geometry/linear_array.svg'), '直线阵列',self)
        act.triggered.connect(lambda:on_exec_geoperiodic_button_click(self))
        pannelView.addLargeAction(act)

        act = QAction(svg_to_ico(current_dir + '/../resource/Geometry/rotate_array.svg'), '旋转阵列',self)
        act.triggered.connect(lambda:on_exec_rotateperiodic_button_click(self))
        pannelView.addLargeAction(act)

        act = QAction(svg_to_ico(current_dir + '/../resource/Geometry/查找特征.svg'), '查找小特征',self)
        act.triggered.connect(lambda:on_exec_findsmallfeature_button_click(self))
        pannelView.addLargeAction(act)

        act = QAction(svg_to_ico(current_dir + '/../resource/Geometry/查找圆角.svg'), '查找圆角',self)
        act.triggered.connect(lambda:on_exec_findfillets_button_click(self))
        pannelView.addLargeAction(act)

        act = QAction(svg_to_ico(current_dir + '/../resource/Geometry/查找LOGO.svg'), '查找LOGO',self)
        act.triggered.connect(lambda:on_exec_findlogos_button_click(self))
        pannelView.addLargeAction(act)

        act = QAction(svg_to_ico(current_dir + '/../resource/Geometry/查找孔.svg'), '查找孔',self)
        act.triggered.connect(lambda:on_exec_findholes_button_click(self))
        pannelView.addLargeAction(act)

    def createCategorySimulation(self,page: SARibbonCategory):
        pannelSimulation = page.addPannel('仿真')
        pannelSimulation.setStyleSheet("font-size: {}pt".format(self.fontSize))
        current_dir = os.path.dirname(os.path.abspath(__file__))
        act = QAction(svg_to_ico(current_dir + '/../resource/Simulation/create_surface_mesh.svg'), '面网格',self)
        act.triggered.connect(lambda:on_mesh_surface_generation(self))
        pannelSimulation.addLargeAction(act)
        
        act = QAction(svg_to_ico(current_dir + '/../resource/Simulation/create_volume_mesh.svg'), '体网格',self)
        act.triggered.connect(lambda:on_mesh_volume_generation(self))
        pannelSimulation.addLargeAction(act)
        pannelSimulation.addSeparator() 

        act = QAction(svg_to_ico(current_dir + '/../resource/Simulation/mesh_add_force.svg'), '集中力',self)
        act.triggered.connect(lambda:on_single_force(self))
        pannelSimulation.addLargeAction(act)

        act = QAction(svg_to_ico(current_dir + '/../resource/Simulation/mesh_add_spc.svg'), '单点约束',self)
        act.triggered.connect(lambda:on_single_constraint(self))
        pannelSimulation.addLargeAction(act)

        act = QAction(svg_to_ico(current_dir + '/../resource/Simulation/mesh_add_mat.svg'), '材料属性',self)
        act.triggered.connect(lambda:on_material_properties(self))
        pannelSimulation.addLargeAction(act)

        act = QAction(svg_to_ico(current_dir + '/../resource/Simulation/mesh_setting.svg'), '网格拾取',self)
        act.setEnabled(True)
        pannelSimulation.addLargeAction(act)

        self.mesh_geo = QRadioButton("几何")
        self.mesh_geo.clicked.connect(lambda :on_set_pickup_mesh(self, 0))
        self.mesh_geo.setChecked(True)
        pannelSimulation.addSmallWidget(self.mesh_geo)
        
        self.mesh_node = QRadioButton("节点")
        self.mesh_node.clicked.connect(lambda :on_set_pickup_mesh(self, 1))
        pannelSimulation.addSmallWidget(self.mesh_node)
        
        self.mesh_unit = QRadioButton("单元")
        self.mesh_unit.clicked.connect(lambda :on_set_pickup_mesh(self, 2))
        pannelSimulation.addSmallWidget(self.mesh_unit)
        
        self.mesh_unit_face = QRadioButton("单元面")
        self.mesh_unit_face.clicked.connect(lambda :on_set_pickup_mesh(self, 3))
        pannelSimulation.addSmallWidget(self.mesh_unit_face)

        self.mesh_unit_line = QRadioButton("单元边")
        self.mesh_unit_line.clicked.connect(lambda :on_set_pickup_mesh(self, 4))
        pannelSimulation.addSmallWidget(self.mesh_unit_line)
        self.meshpickup_grpbtn = QButtonGroup(self)
        self.meshpickup_grpbtn.addButton(self.mesh_geo)
        self.meshpickup_grpbtn.addButton(self.mesh_node)
        self.meshpickup_grpbtn.addButton(self.mesh_unit)
        self.meshpickup_grpbtn.addButton(self.mesh_unit_face)
        self.meshpickup_grpbtn.addButton(self.mesh_unit_line)

        act = QAction(svg_to_ico(current_dir + '/../resource/Simulation/mesh_setting.svg'), '全部显示',self)
        act.triggered.connect(lambda:on_set_visibility_all_show(self))
        pannelSimulation.addLargeAction(act)

        act = QAction(svg_to_ico(current_dir + '/../resource/Simulation/mesh_setting.svg'), '隐藏',self)
        act.setEnabled(True)
        act.triggered.connect(lambda:on_set_visibility_by_sel(self,False))
        pannelSimulation.addLargeAction(act)

        act = QAction(svg_to_ico(current_dir + '/../resource/Simulation/mesh_setting.svg'), '仅显示',self)
        act.setEnabled(True)
        act.triggered.connect(lambda:on_set_visibility_only_show_by_sel(self))
        pannelSimulation.addLargeAction(act)


    def onStyleClicked(self, sty: int):
        self.ribbonBar().setRibbonStyle(sty)

    def autoSizeView(self):
        if hasattr(self, 'doc'):            
            self.cad_view.resizeEvent(None)
            self.updateTree()

    def keyPressEvent(self, QKeyEvent):#重写按键事件
        if QKeyEvent.key()==Qt.Key_A:#按A建
            print("A")
            # self.btn1.click()
        if  QKeyEvent.key()==Qt.Key_Tab:
            print("TABTAB")

    def closeEvent(self, QCloseEvent):#重写关闭窗口事件
        if hasattr(self, 'doc'):
            self.doc.Close()
        print("重写关闭窗口事件closeEvent")

    def resizeEvent(self, event):
        self.update()
        self.autoSizeView()
        
    def changeEvent(self, event):
        if event.type() == QEvent.Type.WindowStateChange:
            if self.windowState() == Qt.WindowState.WindowMinimized:
                return
            elif self.windowState() == Qt.WindowState.WindowNoState:
                self.doc.Update()

    def on_create_cube(self):
        if False == hasattr(self, 'doc'):
            return        
        self.doc.RunCommand("cmd_ncti_create_box","", 10, 20, 30)


    def on_cavity_button_click(self):
        if hasattr(self, 'doc'):
            self.hexahedron()

    def on_run_script_button_click(self):
        if False == hasattr(self, 'doc'):
            return
        code = self.editor_script.selectedText()
        if len(code) == 0:
            code = self.editor_script.text()
        if len(code) == 0:
            return
        global global_scope
        global_scope["doc"] = self.doc
        try:
            # exec(code, global_scope)
            exec(code, global_scope)  # 执行脚本
            print("执行完毕")
        except Exception as e:
            print(f"执行脚本发生了错误: {e}")
            #QMessageBox.critical(self, "错误", f"执行脚本发生了错误: {e}")
            return
        self.updateTree()

    def on_open_script_button_click(self):
        get_filename_path, ok = QFileDialog.getOpenFileName(self,
                                "选取Py脚本文件",
                               "D:/",
                                "Python Files (*.py)")
        if ok:
            with open(str(get_filename_path), 'r', encoding='utf-8') as file:
                self.editor_script.setText(file.read())
                

    def on_exec_file_button_click(self):
        if False == hasattr(self, 'doc'):
            return        
        get_filename_path, ok = QFileDialog.getOpenFileName(self,
                                "选取Py脚本文件",
                               "D:/",
                                "Python Files (*.py)")
        if ok:
            global global_scope
            with open(str(get_filename_path), 'r', encoding='utf-8') as file:
                global_scope["NCTI"] = self.NCTI
                global_scope["doc"] = self.doc
                try:
                    exec(file.read(), global_scope)
                    self.doc.Zoom()
                except Exception as e:
                    print(f"执行脚本发生了错误: {e}")
                    QMessageBox.critical(self, "错误", f"执行脚本发生了错误: {e}")
                    return
                
    def on_physical_modeling(self, text):
        if False == hasattr(self, 'doc'):
            return
        file = "scripts/" + text.replace("\n", "") + ".py"
        global global_scope
        with open(str(file), 'r', encoding='utf-8') as file:
            global_scope["NCTI"] = self.NCTI
            global_scope["doc"] = self.doc
            try:
                exec(file.read(), global_scope)
            except Exception as e:
                print(f"{text} 发生了{e}")   
    
    def init_CAD_Env(self):
        global global_scope
        if "NCTI" in global_scope:
            self.NCTI = global_scope["NCTI"]
            self.doc = global_scope["doc"] 
            return True
        else:
            return False


    # 侧边栏相关
    def initObjectTreeDocWidget(self):
        self.objectTree.setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Expanding)
        self.objectTreeTitleBar.setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Preferred)
        self.objectTreeTitleBar.setTitle("对象树")
        self.objectTreeDocWidget.setTitleBarWidget(self.objectTreeTitleBar)
        self.objectTreeDocWidget.setWidget(self.objectTree)
        self.objectTreeDocWidget.setAllowedAreas(Qt.LeftDockWidgetArea)
        self.objectTreeDocWidget.setFeatures(QDockWidget.NoDockWidgetFeatures)
        self.objectTreeDocWidget.setMinimumWidth(0)

        self.objectTree.sigSidePannelVisible.connect(lambda visable: self.onSidePannelVisible(visable))
        self.objectTree.objectTreeView.selectionModel().selectionChanged.connect(self.onUpdateModelByTree)
        self.objectTree.objectTreeView.treeBecameEmpty.connect(self.onClearPorperty) 

    def onSidePannelVisible(self, visible):
        try:
            if visible:
                if not self.objectTreeDocWidget or not self.objectTreeTitleBar:
                    raise RuntimeError("objectTreeDocWidget or objectTreeTitleBar is not initialized!")
                
                self.objectTreePannelVisible = True
                self.objectTreeTitleBar.setTitle("对象树")
                self.objectTreeDocWidget.setMinimumWidth(200)
                self.objectTreeDocWidget.setMaximumWidth(16777215)
            else:
                self.objectTreePannelVisible = False
                self.objectTreeTitleBar.setTitle("")
                self.objectTreeDocWidget.setMinimumWidth(40)
                self.objectTreeDocWidget.setMaximumWidth(40)
        except Exception as e:
            print(f"Error: {e}")
            import traceback
            traceback.print_exc()

    def initRightDocWidget(self):
        self.rightView.setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Expanding)
        self.rightDocTitleBar.setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Preferred)
        self.rightDocTitleBar.setTitle("脚本编辑")
        self.rightDocWidget.setTitleBarWidget(self.rightDocTitleBar)
        self.rightDocWidget.setWidget(self.rightView)
        self.rightDocWidget.setAllowedAreas(Qt.RightDockWidgetArea)
        self.rightDocWidget.setFeatures(QDockWidget.NoDockWidgetFeatures)
        self.rightDocWidget.setMinimumWidth(0)

        self.rightView.sigRightSidePannelVisible.connect(lambda id, visible: self.onRigehSidePannelVisible(id, visible))

    def onRigehSidePannelVisible(self, id, visible):
        if visible:
            self.rightPannelVisible = True
            title = ""
            if id == 0:
                title = "脚本编辑"
            elif id == 1:
                title = "属性"
            self.rightDocTitleBar.setTitle(title)
            self.rightDocWidget.setMinimumWidth(200)
            self.rightDocWidget.setMaximumWidth(16777215)
        else:
            self.rightPannelVisible = False
            self.rightDocTitleBar.setTitle("")
            self.rightDocWidget.setMinimumWidth(40)
            self.rightDocWidget.setMaximumWidth(40)

    def getCurrentObjectData(self):
        sel = self.NCTI.SelectionManager(self.doc)
        objecNameList = self.doc.AllNames()
        if not objecNameList:
            return
        modelDateList = []
        for index, object_name in enumerate(objecNameList, start=1):
            item = PythonTreeModelData()
            item.text = f"实体{index}"
            item.objName = object_name
            modelDateList.append(item)
        return modelDateList
    

    def updateTree(self):
        if self.objectTree:
            self.objectTree.SetModelData(self.getCurrentObjectData())

    def onClearPorperty(self):
        self.rightView.objectProperty.propertyTree.clear_properties()

    def onUpdateModelByTree(self):
        all_selected_indexes = self.objectTree.objectTreeView.selectionModel().selectedIndexes()
        objNames = []
        if all_selected_indexes:
            self.selectTree = True
            for item in all_selected_indexes:  
                model = item.model()
                user_data = model.data(item, Qt.UserRole) 

                if hasattr(user_data, "objName"):
                    obj_name = user_data.objName
                    objNames.append(obj_name)

                if hasattr(user_data, "text"):
                    dispaly_name = user_data.text
                if hasattr(user_data, "objName"):
                    obj_name = user_data.objName
                type_name = re.sub(r'_\d+$', '', obj_name)
                box = self.doc.GetBoundingBox(obj_name)
                obj_x = box[3] - box[0]
                obj_y = box[4] - box[1]
                obj_z = box[5] - box[2]
                self.rightView.objectProperty.propertyTree.set_property_data(
                    dispaly_name, obj_name, type_name, obj_x, obj_y, obj_z
                )
        else:
            self.updateModelView(objNames)
            return
        self.updateModelView(objNames)

    def onUpdateTreeByModel(self, list):
        model = self.objectTree.objectTreeView.model()
        selection_model = self.objectTree.objectTreeView.selectionModel()
        if list and model:
            for row in range(model.rowCount()):
                index = model.index(row, 0)  # 第 0 列
                if not index.isValid():
                    continue
                data = model.data(index, Qt.UserRole)
                if data and data.objName in list:
                    selection_model.select(index, selection_model.Select)


    def updateModelView(self, objectNameList):
        sel = self.NCTI.SelectionManager(self.doc)
        sel.ClearSelected()
        sel.ObjectNames = objectNameList
        sel.SetSelected()
        self.doc.Update()# 强制刷新界面

    def getFontSize(self):
        local_dpi = self.logicalDpiX()
        fontSize = 9
        if local_dpi > 96:
                fontSize = int(9 * (96 / local_dpi)) + 1
        return fontSize
            